home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / vol6n13.arc / PAD.ASM < prev    next >
Assembly Source File  |  1987-07-03  |  26KB  |  620 lines

  1. INTERRUPTS      SEGMENT AT 0H   ;This is where the keyboard interrupt
  2.         ORG     9H*4            ;holds the address of its service routine
  3. KEYBOARD_INT    LABEL   WORD  
  4.         ORG     21H*4            ;holds the address of its service routine
  5. DOS_INT        LABEL   WORD  
  6. INTERRUPTS      ENDS
  7.  
  8. SCREEN  SEGMENT AT 0B000H       ;A dummy segment to use as the
  9. SCREEN  ENDS                    ;Extra Segment 
  10.  
  11. ROM_BIOS_DATA   SEGMENT AT 40H  ;BIOS statuses held here, also keyboard buffer
  12.  
  13.         ORG     1AH
  14.         HEAD DW      ?                  ;Unread chars go from Head to Tail
  15.         TAIL DW      ?
  16.         BUFFER       DW      16 DUP (?)         ;The buffer itself
  17.         BUFFER_END   LABEL   WORD
  18.  
  19. ROM_BIOS_DATA   ENDS
  20.  
  21. CODE_SEG        SEGMENT
  22.         ASSUME  CS:CODE_SEG
  23.         ORG     100H            ;ORG = 100H to make this into a .COM file
  24. FIRST:  JMP     LOAD_PAD        ;First time through jump to initialize routine
  25.  
  26.         COPY_RIGHT      DB '(C)1987 S Holzner'
  27.         INT21   LABEL   DWORD   ;Point to next two words for jump.
  28.         OLD_DOS_INT     DW 2 DUP(?)     ;Store original DOS INT21 address here.
  29.         FIRST_FLAG      DB 1            ;First time through? Get COMMAND address
  30.         COMMAND_ADDR    DW ?            ;Store IP of calling routine in COMMAND.
  31.         OLD_DS          DW 1            ;Keep DS:DX of old keyboard buffer.
  32.         OLD_DX          DW 1001H
  33.         KEY1    DB 'SAVE', 0DH 
  34.         KEY2    DB 'save', 0DH 
  35.         KEY3    DB 'Save'
  36.         CR      DB  0DH,0AH,'$'         ;Use this <cr> to send to DOS.
  37.         FILE_DONE       DB      0DH,0AH,'PAD.TXT created.',0DH,0AH,'$'
  38.         CNTRL_N_FLAG    DW      0               ;Cntrl-N on or off
  39.         FILENAME        DB      'PAD.TXT',0
  40.         PAD_CURSOR      DW      0               ;Current position in pad
  41.         CURSOR_STORAGE  DW      0,600,1200,1800,2400  ;Hold cursor each page.
  42.         PAD_OFFSET      DW      0               ;Chooses 1st 250 bytes or 2nd
  43.         PAD_BEGIN       DW      0               ;Beginning of current page.
  44.         PAD_END         DW      599             ;End of current page.
  45.         PAGE_NUMBER     DW      0               ;Page Number 0-4.
  46.         FIRST_POSITION  DW      ?               ;Position of 1st char on screen
  47.         ATTRIBUTE       DB      112 ;Pad Attribute: 1EH better for color screens
  48.         FORE_ATTR       DB      0
  49.         BACK_ATTR       DB      0
  50.         SCREEN_SEG_OFFSET       DW      0       ;0 for mono, 8000H for graphics
  51.         IO_CHAR         DW      ?               ;Holds addr of Put or Get_Char
  52.         STATUS_PORT     DW      ?               ;Video controller status port
  53.         OLD_KEY_INT     LABEL   WORD
  54.         OLD_KEYBOARD_INT        DD      ?       ;Location of old kbd interrupt
  55.  
  56. NEWPAD  PROC    NEAR            ;The keyboard interrupt will now come here.
  57.         ASSUME  CS:CODE_SEG
  58.         PUSH    AX              ;Save the used registers for good form
  59.         PUSH    BX
  60.         PUSH    CX
  61.         PUSH    DX
  62.         PUSH    DI
  63.         PUSH    SI
  64.         PUSH    DS
  65.         PUSH    ES
  66.         PUSHF                   ;First, call old keyboard interrupt
  67.         CALL    OLD_KEYBOARD_INT
  68.  
  69.         ASSUME  DS:ROM_BIOS_DATA        ;Examine the char just put in
  70.         MOV     BX,ROM_BIOS_DATA
  71.         MOV     DS,BX
  72.  
  73.         MOV     BX,TAIL                 ;Point to current tail
  74.         CMP     BX,HEAD                 ;If at head, kbd int has deleted char
  75.         JE      IN                      ;So leave 
  76.         SUB     BX,2                    ;Point to just read in character
  77.         CMP     BX,OFFSET BUFFER        ;Did we undershoot buffer?
  78.         JAE     NO_WRAP                 ;Nope
  79.         MOV     BX,OFFSET BUFFER_END    ;Yes -- move to buffer top
  80.         SUB     BX,2                    ;Point to just read in characterqqq
  81. NO_WRAP:MOV     DX,[BX]                 ;Char in DX now
  82.         CMP     DX,310EH                ;Is the char a Cntrl-N?
  83.         JNE     NOT_CNTRL_N             ;No
  84.         MOV     TAIL,BX                 ;Yes -- delete it from buffer
  85.         NOT     CNTRL_N_FLAG            ;Switch Modes
  86.         CMP     CNTRL_N_FLAG,0          ;Cntrl-N off?
  87.         JNE     CNTRL_N_ON              ;No, only other choice is on
  88. CNTRL_N_OFF:
  89.         LEA     DX,PAD
  90.         MOV     PAD_OFFSET,DX
  91.         ADD     PAD_OFFSET,3000
  92.         LEA     AX,PUT_CHAR             ;Make IO call Put_Char as it scans
  93.         MOV     IO_CHAR,AX              ;over all locations in pad on screen
  94.         CALL    IO                      ;Restore screen
  95. IN:     JMP     OUT                     ;Done
  96. CNTRL_N_ON:
  97.         LEA     DX,PAD
  98.         MOV     PAD_OFFSET,DX
  99.         ADD     PAD_OFFSET,3000
  100.         LEA     AX,GET_CHAR             ;Make IO use Get_char so current screen
  101.         MOV     IO_CHAR,AX              ;is stored
  102.         CALL    IO                      ;Store Screen
  103.         CALL    DISPLAY                 ;And put up the pad
  104.         JMP     OUT                     ;Done here.
  105. NOT_CNTRL_N:
  106.         TEST    CNTRL_N_FLAG,1          ;Is Cntrl-N on?
  107.         JZ      IN                      ;No -- leave
  108.         MOV     TAIL,BX                 ;Yes, delete this char from buffer
  109.         CMP     DX,5300H                ;Decide what to do -- is it a Delete?
  110.         JNE     RUBOUT_TEST             ;No -- try Rubout
  111.         PUSH    DS
  112.         PUSH    CS
  113.         POP     DS
  114.         MOV     BX,PAD_END
  115.         DEC     BX
  116. DEL_LOOP:
  117.         MOV     BYTE PTR [BX],' '       ;Move space to current pad position
  118.         DEC     BX                      ;and go back one
  119.         CMP     BX,PAD_BEGIN
  120.         JNZ     DEL_LOOP                ;until done.
  121.         MOV     BYTE PTR [BX],'_'       ;Put the cursor at the beginning
  122.         MOV     DX,PAD_BEGIN
  123.         MOV     PAD_CURSOR,dx   ;qq         ;And start cursor over
  124.         POP     DS
  125.         CALL    DISPLAY                 ;Put up the new pad on screen
  126.         JMP     OUT                     ;And take our leave
  127. RUBOUT_TEST:
  128.         CMP     DX,0E08H                ;Is it a Rubout?
  129.         JNE     CRLF_TEST               ;No -- try carriage return-line feed
  130.         PUSH    DS
  131.         PUSH    CS
  132.         POP     DS
  133.         MOV     BX,PAD_CURSOR           ;Yes -- get current pad location
  134.         CMP     BX,PAD_BEGIN            ;Are we at beginning?
  135.         JLE     NEVER_MIND              ;Yes -- can't rubout past beginning
  136.         MOV     BYTE PTR [BX-1],'_'           ;And move cursor back one
  137.         DEC     PAD_CURSOR              ;Set the pad location straight
  138.         CMP     BX,PAD_END              ;Save page number.
  139.         JE      NEVER_MIND
  140.         MOV     BYTE PTR [BX],' '       ;No -- move space to current position
  141. NEVER_MIND:
  142.         POP     DS
  143.         CALL    DISPLAY                 ;And put the result on the screen
  144.         JMP     OUT                     ;Done here.
  145. CRLF_TEST:
  146.         CMP     DX,1C0DH                ;Is it a carriage return-line feed?
  147.         JNE     PGUP_TEST               ;No 
  148.         PUSH    DS
  149.         PUSH    CS
  150.         POP     DS
  151.         CALL    CRLF                    ;Yes -- move to next line
  152.         POP     DS
  153.         CALL    DISPLAY                 ;And display result on screen
  154.         JMP     OUT                     ;Done.
  155. PGUP_TEST:
  156.         CMP     DX,4900H
  157.         JNE     PGDN_TEST
  158.         CMP     PAGE_NUMBER,0
  159.         JNE     DEC_PAGE
  160.         JMP     OUT
  161. DEC_PAGE:
  162.         MOV     BX,PAGE_NUMBER          ;STORE PAD CURSOR
  163.         ADD     BX,BX
  164.         MOV     CX,PAD_CURSOR
  165.         MOV     CURSOR_STORAGE[BX],CX
  166.         DEC     PAGE_NUMBER
  167.         SUB     BX,2
  168.         MOV     CX,CURSOR_STORAGE[BX]
  169.         MOV     PAD_CURSOR,CX
  170.  
  171.         MOV     AX,PAGE_NUMBER
  172.         MOV     BX,600
  173.         MUL     BX
  174.         LEA     DX,PAD
  175.         ADD     AX,DX   
  176.         MOV     PAD_BEGIN,AX
  177.         ADD     AX,599
  178.         MOV     PAD_END,AX
  179.         CALL    DISPLAY
  180.         JMP     OUT
  181. PGDN_TEST:
  182.         CMP     DX,5100H
  183.         JNE     F1_TEST
  184.         CMP     PAGE_NUMBER,4
  185.         JNE     INC_PAGE
  186.         JMP     OUT
  187. INC_PAGE:
  188.         MOV     BX,PAGE_NUMBER          ;Store pad cursor.
  189.         ADD     BX,BX
  190.         MOV     CX,PAD_CURSOR
  191.         MOV     CURSOR_STORAGE[BX],CX
  192.         INC     PAGE_NUMBER
  193.         ADD     BX,2
  194.         MOV     CX,CURSOR_STORAGE[BX]
  195.         MOV     PAD_CURSOR,CX
  196.         MOV     AX,PAGE_NUMBER
  197.         MOV     BX,600
  198.         MUL     BX
  199.         LEA     DX,PAD
  200.         ADD     AX,DX   
  201.         MOV     PAD_BEGIN,AX
  202.         ADD     AX,599
  203.         MOV     PAD_END,AX
  204.         CALL    DISPLAY
  205.         JMP     OUT
  206. F1_TEST:CMP     DX,3B00H
  207.         JNE     F2_TEST
  208.         MOV     AH,FORE_ATTR
  209.         INC     AH
  210.         CMP     AH,16
  211.         JL      OKFORE
  212.         MOV     AH,0
  213. OKFORE: MOV     FORE_ATTR,AH
  214.         AND     ATTRIBUTE,240   ;Clear fore color
  215.         OR      ATTRIBUTE,AH
  216.         CALL    DISPLAY
  217.         JMP     OUT
  218. F2_TEST:CMP     DX,3C00H
  219.         JNE     CHAR_TEST
  220.         MOV     AH,BACK_ATTR
  221.         ADD     AH,16
  222.         CMP     AH,120
  223.         JB      OKBACK
  224.         MOV     AH,0
  225. OKBACK: MOV     BACK_ATTR,AH
  226.         AND     ATTRIBUTE,15    ;Clear back color
  227.         OR      ATTRIBUTE,AH
  228.         CALL    DISPLAY
  229.         JMP     OUT
  230. CHAR_TEST:                                                     
  231.         PUSH    DS
  232.         PUSH    CS
  233.         POP     DS
  234.         MOV     BX,PAD_CURSOR           ;Get current pad location
  235.         CMP     BX,PAD_END                  ;Are we past the end of the pad?
  236.         JGE     PAST_END                ;Yes -- throw away char
  237.         MOV     byte ptr [bx],DL              ;No -- move ASCII code into pad
  238.         INC     PAD_CURSOR              ;Increment pad location
  239.         INC     BX
  240.         CMP     BX,PAD_END
  241.         JE      PAST_END
  242.         MOV     BYTE PTR [BX],'_'           ;Advance cursor
  243. PAST_END:         
  244.         POP     DS
  245.         CALL    DISPLAY                 ;Put result on screen
  246. OUT:    POP     ES      ;Having done Pushes, here are the Pops
  247.         POP     DS
  248.         POP     SI
  249.         POP     DI
  250.         POP     DX
  251.         POP     CX
  252.         POP     BX
  253.         POP     AX     
  254.         IRET                    ;An interrupt needs an IRET
  255. NEWPAD  ENDP
  256.  
  257. DISPLAY PROC    NEAR                    ;Puts the whole pad on the screen
  258.         PUSH    AX
  259.         PUSH    PAD_BEGIN
  260.         POP     PAD_OFFSET
  261.         LEA     AX,PUT_CHAR             ;Make IO use Put-Char so it does
  262.         MOV     IO_CHAR,AX              
  263.         CALL    IO                      ;Put result on screen
  264.         POP     AX
  265.         RET                             ;Leave
  266. DISPLAY ENDP
  267.  
  268. CRLF    PROC    NEAR                    ;This handles carriage returns
  269.         MOV     DI,PAD_END       ;Are we on last line?
  270.         SUB     DI,40
  271.         CMP     PAD_CURSOR,DI
  272.         JGE     DONE                    ;Yes, can't do a carriage return, exit
  273. NEXT_CHAR:
  274.         MOV     BX,PAD_CURSOR           ;Get pad location
  275.         MOV     AX,BX                   ;Get another copy for destructive tests
  276.         SUB     AX,PAD_BEGIN    
  277. EDGE_TEST:
  278.         CMP     AX,39                   ;Are we at the edge of the pad display?
  279.         JE      AT_EDGE                 ;Yes -- fill pad with new cursor
  280.         JL      ADD_SPACE               ;No -- Advance another space
  281.         SUB     AX,40                   ;Subtract another line-width
  282.         JMP     EDGE_TEST               ;Check if at edge now
  283. ADD_SPACE:
  284.         MOV     BYTE PTR [BX],' '             ;Add a space
  285.         INC     PAD_CURSOR              ;Update pad location
  286.         JMP     NEXT_CHAR               ;Check if at edge now
  287. AT_EDGE:
  288.         MOV     BYTE PTR [BX],' '
  289.         MOV     BYTE PTR [BX+1],'_'           ;Put cursor in next location
  290.         INC     PAD_CURSOR              ;Update pad location to new cursor
  291. DONE:   RET                             ;And out.
  292. CRLF    ENDP
  293.  
  294. GET_CHAR        PROC    NEAR    ;Gets a char from screen and advances position
  295.         PUSH    DS
  296.         PUSH    DX
  297.         PUSH    CS
  298.         POP     DS
  299.  
  300.         MOV     SI,2            ;Loop twice, once for char, once for attribute
  301.         MOV     DX,STATUS_PORT  ;Get ready to read video controller status
  302.  
  303. G_WAIT_LOW:                     ;Start waiting for a new horizontal scan -
  304.         IN      AL,DX           ;Make sure the video controller scan status
  305.         TEST    AL,1            ;is low
  306.         JNZ     G_WAIT_LOW
  307. G_WAIT_HIGH:                    ;After port has gone low, it must go high
  308.         IN      AL,DX           ;before it is safe to read directly from
  309.         TEST    AL,1            ;the screen buffer in memory
  310.         JZ      G_WAIT_HIGH
  311.  
  312.         MOV     AH,ES:[DI]      ;Do the move from the screen, one byte at a time
  313.         INC     DI              ;Move to next screen location                   
  314.         DEC     SI              ;Decrement loop counter
  315.         CMP     SI,0            ;Are we done?
  316.         JE      LEAVE           ;Yes
  317.         MOV     BYTE PTR [BX],AH      ;No -- put char we got into the pad
  318.         JMP     G_WAIT_LOW      ;Do it again
  319. LEAVE:  INC     BX              
  320.         MOV     BYTE PTR [BX],AH
  321.         INC     BX              ;Update pad location
  322.         POP     DX
  323.         POP     DS
  324.         RET 
  325. GET_CHAR        ENDP
  326.  
  327. PUT_CHAR        PROC    NEAR    ;Puts one char on screen and advances position
  328.         PUSH    DS
  329.         PUSH    CX
  330.         PUSH    DX
  331.         PUSH    CS
  332.         POP     DS
  333.         MOV     AH,BYTE PTR [BX]      ;Get the char to be put onto the screen
  334.         MOV     SI,2            ;Loop twice, once for char, once for attribute
  335.         MOV     DX,STATUS_PORT  ;Get ready to read video controller status
  336. P_WAIT_LOW:                     ;Start waiting for a new horizontal scan -
  337.         IN      AL,DX           ;Make sure the video controller scan status
  338.         TEST    AL,1            ;is low
  339.         JNZ     P_WAIT_LOW
  340. P_WAIT_HIGH:                    ;After port has gone low, it must go high
  341.         IN      AL,DX           ;before it is safe to write directly to
  342.         TEST    AL,1            ;the screen buffer in memory
  343.         JZ      P_WAIT_HIGH
  344.         MOV     ES:[DI],AH      ;Move to screen, one byte at a time
  345.    
  346.         LEA     CX,PAD
  347.         ADD     CX,3000
  348.         CMP     PAD_OFFSET,CX
  349.         JNE     GET_ATT         ;We are restoring pad here.
  350.         MOV     AH,BYTE PTR [BX+1]      
  351.         JMP     SHORT   INCDI
  352.  
  353. GET_ATT:MOV     AH,ATTRIBUTE    ;Load attribute byte for second pass
  354. INCDI:  INC     DI              ;Point to next screen postion
  355.         DEC     SI              ;Decrement loop counter
  356.         JNZ     P_WAIT_LOW      ;If not zero, do it one more time
  357.         INC     BX              ;Point to next char in pad
  358.         LEA     CX,PAD
  359.         ADD     CX,3000
  360.         CMP     PAD_OFFSET,CX
  361.         JNE     RETRN
  362.         INC     BX
  363. RETRN:  POP     DX
  364.         POP     CX
  365.         POP     DS
  366.         RET                     ;Exeunt
  367. PUT_CHAR        ENDP
  368.  
  369. IO      PROC    NEAR           ;This scans over all screen positions of the pad
  370.         ASSUME  ES:SCREEN               ;Use screen as extra segment
  371.         MOV     BX,SCREEN
  372.         MOV     ES,BX
  373.         MOV     DI,SCREEN_SEG_OFFSET    ;DI will be pointer to screen postion
  374.         ADD     DI,FIRST_POSITION       ;Add width of screen minus pad width
  375.         MOV     BX,PAD_OFFSET           ;BX will be pad location pointer
  376.         MOV     CX,15                   ;There will be 10 lines
  377. LINE_LOOP:      
  378.         MOV     DX,40                   ;And 25 spaces across
  379. CHAR_LOOP:
  380.         CALL    IO_CHAR                 ;Call Put-Char or Get-Char
  381.         DEC     DX                      ;Decrement character loop counter
  382.         JNZ     CHAR_LOOP               ;If not zero, scan over next character
  383.         ADD     DI,FIRST_POSITION       ;Add width of screen minus pad width
  384.         LOOP    LINE_LOOP               ;And now go back to do next line
  385.         RET                             ;Finished
  386. IO      ENDP
  387.  
  388. DOS_WATCH      PROC    FAR              ;The DOS interrupt will now come here.
  389.         PUSH    ES                      ;Save all used registers.
  390.         PUSH    DS
  391.         PUSH    BP
  392.         PUSH    AX 
  393.         PUSH    BX
  394.         PUSH    CX
  395.         CMP     AH,0AH                  ;Is this the DOS Service we want to
  396.         JE      GO                      ; intercept?
  397.         JMP     OUT2                     ;No.
  398. GO:     MOV     BX,DX                   ;Yes. Get length of original buffer.
  399.         MOV     CL,BYTE PTR DS:[BX]
  400.         PUSH    DS                      ;Save DS:DX, address of original buffer.
  401.         ASSUME DS:CODE_SEG
  402.         PUSH    CS                      ;Make DS=CS to use local labels.
  403.         POP     DS
  404.         POP     OLD_DS
  405.         PUSH    DX
  406.         POP     OLD_DX
  407.         MOV     BX,80H                  ;We will use DS:80H for our buffer.
  408.         MOV     BYTE PTR DS:[BX],CL     ;Store legal length from original buff.
  409.         MOV     BP,SP                   ;Prepare to get IP of return address.
  410.         CMP     FIRST_FLAG,1            ;First time through?
  411.         JNE     NOT_FIRST               ;No -- check if COMMAND.COM is calling.
  412.         MOV     BX,SS:[BP+4]            ;Yes, SHORTHND.COM must have just ended,
  413.         MOV     COMMAND_ADDR,BX         ; so we are at monitor level -- get
  414.         MOV     FIRST_FLAG,0            ; calling addr in COMMAND.COM from stack
  415.         PUSH    AX
  416.         PUSH    CX
  417.         PUSH    DI
  418.         PUSH    ES
  419.  
  420.         PUSH    CS
  421.         POP     ES
  422.         LEA     DI,PAD
  423.         MOV     CX,3000
  424.         MOV     AL,' '
  425. REP     STOSB
  426.         LEA     DI,PAD
  427.         MOV     AL,'1'
  428.         MOV     CX,5
  429. LLOOP:  MOV     BYTE PTR [DI],'_'
  430.         MOV     [DI+599],AL
  431.         INC     AL
  432.         ADD     DI,600
  433.         LOOP    LLOOP
  434.         
  435.         POP     ES
  436.         POP     DI
  437.         POP     CX
  438.         POP     AX
  439.  
  440.         JMP     INTERCEPT       ;Since we are at monitor level, intercept.
  441. NOT_FIRST:                      ;Not the first time through, check COMMAND addr.
  442.         MOV     BX,SS:[BP+4]            ;Get ret addr from stack.
  443.         CMP     BX,COMMAND_ADDR         ;Compare to what we know is COMMAND.COM
  444.         JE      INTERCEPT               ;If not equal, not at monitor level.
  445.         JMP     OUT2                     ;If not equal, not at monitor level.
  446. INTERCEPT:              ;We are at monitor level, check for keys being typed.
  447.         MOV     DX,80H          ;Get typein to OUR buffer instead of COMMAND's.
  448.         MOV     AH,0AH          ;Use Service 0AH.
  449.         PUSHF           ;CALL INT 21 (we would intercept and INT 21 instruction)
  450.         CALL    INT21
  451.         PUSHF                   ;Save flags.
  452.         CLD                     ;Set upward flag for string commands.
  453.         PUSH    CS              ;Set ES to CODE_SEG.
  454.         POP     ES 
  455.  
  456.         LEA     DI,KEY1         ;Start by checking for KEY1.
  457.         MOV     BP,DI           ;BP will hold address of current KEY.
  458.         MOV     AX,3    ;Loop over 3 keys. 
  459. CMPLOOP:MOV     SI,82H          ;Point to the read-in string.
  460.         MOV     BX,81H          ;Get its length.
  461.         XOR     CX,CX           ;Use CX as counted for REPE.
  462.         MOV     CL,BYTE PTR [BX]      
  463.         CMP     CL,0            ;If nothing typed, skip the checking.
  464.         JNG     QIK
  465.         CMP     CL,4            ;If more than 4 characters typed, skip also.
  466.         JG      QIK
  467. REPE    CMPSB                   ;Compare type-in to key.
  468.         JNZ     NEXT            ;If zero flag not set, last char didn't match.
  469.         JCXZ    MAYBE           ;All chars matched. Was it the right length?
  470.         JMP     SHORT NEXT
  471. MAYBE:  CMP     BYTE PTR [DI],0DH ;If next char in key is <cr>, end of key, so
  472.         JE      FOUND           ;typed-in string was the right length.
  473.  
  474. NEXT:   ADD     BP,5           ;Point to next key.
  475.         MOV     DI,BP           ;Fill DI, which changes in REPE CMPSB, from BP.
  476.         DEC     AX              ;BP, unlike DI, will always hold key addr.
  477.         JNZ     CMPLOOP         ;If AX is 0, have checked all keys.
  478.         JMP     SHORT   QIK
  479. ;SEND <CR> AND WRITE FILE - 40 BYTES, THEN <CR><LF> AT A TIME.
  480. FOUND:  MOV     AH,9
  481.         LEA     DX,CR           ;First send a <CR><LF> to monitor.
  482.         PUSHF
  483.         CALL    INT21
  484.  
  485.         LEA     BP,CR
  486.         MOV     AH,3CH
  487.         LEA     DX,FILENAME
  488.         MOV     CX,0
  489.         PUSHF   
  490.         CALL    INT21
  491.         MOV     CX,75
  492.         MOV     BX,AX   ;Get file handle in BX.
  493.         LEA     DX,PAD
  494. FILE_LOOP:
  495.         MOV     AH,40H
  496.         PUSH    CX
  497.  
  498.         MOV     CX,40
  499.         PUSHF
  500.         CALL    INT21   ;Write one line.
  501.         PUSH    DX
  502.         LEA     DX,CR
  503.         MOV     CX,2
  504.         MOV     AH,40H
  505.         PUSHF
  506.         CALL    INT21   ;Write <CR><LF>
  507.         POP     DX
  508.         ADD     DX,40
  509.         POP     CX
  510.         LOOP    FILE_LOOP
  511.         
  512.         MOV     AH,3EH
  513.         PUSHF
  514.         CALL    INT21
  515.         MOV     AH,9
  516.         LEA     DX,FILE_DONE
  517.         PUSHF
  518.         CALL    INT21
  519.  
  520.         POPF          
  521.         JMP     SHORT   SENDCR
  522.  
  523. QIK:    MOV     BP,82H-5        ;No match, point to typed in command.
  524. ;FOUND:  POPF    ;If there was a match, add 5 to BP to get command addr.
  525.         POPF    ;If there was a match, add 5 to BP to get command addr.
  526.         ADD     BP,5
  527. SENDCR: PUSH    OLD_DS          ;Now use MOVSB to move command to COMMAND buffer
  528.         POP     ES                                                        
  529.         MOV     DI,OLD_DX       ;Get DX of DS:DX.
  530.         ADD     DI,2            ;Point to where type-in is to go.
  531.         MOV     SI,BP
  532.         MOV     AL,0            ;AL will hold char count.
  533. FILL:   MOVSB                   ;Move char to COMMAND.
  534.         CMP     BYTE PTR [SI-1],0DH     ;Reached the command's end?
  535.         JE      FINFIL                  ;Yes.
  536.         INC     AL                      ;No, inc char count.
  537.         JMP     FILL                    ;Loop again.
  538. FINFIL: MOV     DI,OLD_DX               ;Done will string move. 
  539.         INC     DI                      ;Give COMMAND char count in its buffer.
  540.         MOV     BYTE PTR ES:[DI],AL
  541.         POP     CX                      ;The POPs.
  542.         POP     BX
  543.         POP     AX
  544.         POP     BP
  545.         POP     DS
  546.         POP     ES
  547.         IRET                            ;Finish with IRET.
  548. OUT2:   POP     CX                      ;The POPs for the case where we don't
  549.         POP     BX                      ; handle Service 0AH.
  550.         POP     AX
  551.         POP     BP
  552.         POP     DS
  553.         POP     ES
  554.         ASSUME  DS:NOTHING
  555.         JMP     INT21                   ;Let INT 21H take over.
  556. DOS_WATCH      ENDP
  557.  
  558. PAD     LABEL BYTE        
  559.  
  560. LOAD_PAD        PROC    NEAR    ;This procedure intializes everything
  561.         ASSUME  DS:ROM_BIOS_DATA        ;Examine the char just put in
  562.         MOV     BX,ROM_BIOS_DATA
  563.         MOV     DS,BX
  564.         LEA     DX,PAD
  565.         MOV     PAD_BEGIN,DX
  566.         MOV     PAD_CURSOR,DX
  567.         MOV     PAD_OFFSET,DX   
  568.         MOV     CX,DX
  569.         ADD     CX,599
  570.         MOV     PAD_END,CX
  571.         MOV     CX,5
  572.         MOV     BX,0
  573. CLOOP:  MOV     CURSOR_STORAGE[BX],DX
  574.         ADD     DX,600
  575.         ADD     BX,2
  576.         LOOP    CLOOP
  577.  
  578.         ASSUME  DS:INTERRUPTS   ;The data segment will be the Interrupt area
  579.         MOV     AX,INTERRUPTS
  580.         MOV     DS,AX
  581.         
  582.         MOV     AX,KEYBOARD_INT         ;Get the old interrupt service routine
  583.         MOV     OLD_KEY_INT,AX     ;address and put it into our location
  584.         MOV     AX,KEYBOARD_INT[2]      ;OLD_KEYBOARD_INT so we can call it.
  585.         MOV     OLD_KEY_INT[2],AX
  586.         
  587.         MOV     KEYBOARD_INT,OFFSET NEWPAD  ;Now load the address of our notepad
  588.         MOV     KEYBOARD_INT[2],CS         ;routine into the keyboard interrupt
  589.         
  590.         
  591.         MOV     AX,DOS_INT         ;Get the old interrupt service routine
  592.         MOV     OLD_DOS_INT,AX     ;address and put it into our location
  593.         MOV     AX,DOS_INT[2]      ;OLD_DOS_INT so we can call it.
  594.         MOV     OLD_DOS_INT[2],AX
  595.         
  596.         MOV     DOS_INT,OFFSET DOS_WATCH  ;Now load the address of DOS_Watch
  597.         MOV     DOS_INT[2],CS         ;routine into the interrupt vector.
  598.  
  599.         MOV     AH,15                   ;Ask for service 15 of INT 10H 
  600.         INT     10H                     ;This tells us how display is set up
  601.         SUB     AH,40                   ;Move to twenty places before edge
  602.         SHL     AH,1                    ;Mult by two (char & attribute bytes)
  603.         MOV     BYTE PTR FIRST_POSITION,AH      ;Set screen cursor
  604.         MOV     STATUS_PORT,03BAH        ;Assume this is a monochrome display
  605.         TEST    AL,4                    ;Is it?
  606.         JNZ     EXIT                    ;Yes - jump out
  607.         MOV     SCREEN_SEG_OFFSET,8000H ;No - set up for graphics display
  608.         MOV     STATUS_PORT,03DAH
  609.  
  610. EXIT:   MOV     DX,OFFSET LOAD_PAD      ;Set up everything but LOAD_PAD to
  611.         add     dx,4200
  612.         INT     27H                     ;stay and attach itself to DOS
  613. LOAD_PAD        ENDP
  614.  
  615.         CODE_SEG        ENDS
  616.         
  617.         END     FIRST   ;END "FIRST" so 8088 will go to FIRST first.
  618.  
  619.  
  620.